#ifndef ENCRYPTOR_H
#define ENCRYPTOR_H

#include <vector>
#include <array>
#include <cstdint>
#include <stdexcept>
#include <sodium.h>
#include "prng.h"
#include "encoder.h"
#include "utils.h"
#include "context.h"
#include "ring_scaling.h"
#include "ring.h"
#include "ring_poly.h"
#include "operand.h"
#include "ring_sampler.h"
#include "keygen.h"
#include "ring_basis_extension.h"
#include "modular_reduction.h"
/* *
 * @class Encryptor
 * @brief 同态加密中的加密器，负责对明文数据进行加密操作。
 *
 * 该类是同态加密过程中的核心组件之一，负责将明文数据转换为加密后的密文。
 * 它提供了加密接口，以及用于管理加密过程中的各种资源（如多项式池和采样器等）的功能。
 */
class Encryptor {
public:
    Context *params;

    Ring *ringQ;
    Ring *ringP;

    std::vector<Poly *> poolQ;
    std::vector<Poly *> poolP;

    GaussianSampler *gaussianSampler;
    TernarySampler *ternarySampler;
    UniformSampler *uniformSampler;

    Encryptor(Context *params);
    // 拷贝构造函数
    Encryptor(const Encryptor &) = delete;
    Encryptor &operator = (const Encryptor &) = delete;
    // 移动构造函数
    Encryptor(Encryptor &&other) = delete;
    Encryptor &operator = (Encryptor &&other) = delete;

    virtual void Encrypt(Plaintext *pt, Ciphertext *ct) = 0;
    virtual Ciphertext *EncryptNew(Plaintext *pt) = 0;

    virtual ~Encryptor() {}
};
/* *
 * @class PkEncryptor
 * @brief 公钥加密器，继承自 Encryptor，使用公钥进行加密操作。
 *
 * 该类继承自 `Encryptor`，专门用于使用公钥进行加密操作。它在加密过程中利用公钥对明文进行加密，生成对应的密文。
 */
class PkEncryptor : public Encryptor {
public:
    PublicKey *pk;

    PkEncryptor(Context *params, PublicKey *key);
    // 拷贝构造函数
    PkEncryptor(const PkEncryptor &) = delete;
    PkEncryptor &operator = (const PkEncryptor &) = delete;
    // 移动构造函数
    PkEncryptor(PkEncryptor &&other) = delete;
    PkEncryptor &operator = (PkEncryptor &&other) = delete;
    void Encrypt(Plaintext *pt, Ciphertext *ct) override;
    Ciphertext *EncryptNew(Plaintext *pt) override;
};
/* *
 * @class SkEncryptor
 * @brief 秘钥加密器，继承自 Encryptor，使用私钥进行加密操作。
 *
 * 该类继承自 `Encryptor`，专门用于使用私钥进行加密操作。它在加密过程中利用私钥对明文进行加密，生成对应的密文。
 */
class SkEncryptor : public Encryptor {
public:
    SecretKey *sk;

    SkEncryptor(Context *params, SecretKey *key);
    // 拷贝构造函数
    SkEncryptor(const SkEncryptor &) = delete;
    SkEncryptor &operator = (const SkEncryptor &) = delete;
    // 移动构造函数
    SkEncryptor(SkEncryptor &&other) = delete;
    SkEncryptor &operator = (SkEncryptor &&other) = delete;
    void Encrypt(Plaintext *pt, Ciphertext *ct) override;
    Ciphertext *EncryptNew(Plaintext *pt) override;
};

#endif // ENCRYPTOR_H